#pragma once
#include<iostream>
#include<queue>
#include<pthread.h>
#include<unistd.h>
#include"Task.hpp"
#include"Log.hpp"

#define NUM 6

class ThreadPool
{
public://资源回收器
    class CGarbo
    {
    public:
        ~CGarbo()
        {
            if(ThreadPool::tp!=nullptr)
                delete ThreadPool::tp;
        }
    };
private:
    int num;
    bool stop;
    std::queue<Task*> q;
    pthread_mutex_t mtx;
    pthread_cond_t cond;
    static ThreadPool* tp;//单例
    static CGarbo cg;//垃圾回收-内嵌
private://单例
    ThreadPool(int _num=NUM):stop(false),num(_num){}
    ThreadPool(const ThreadPool&)=delete;
    ThreadPool& operator=(const ThreadPool&)=delete;
public://封装接口便于调用
    void Lock()
    {
        pthread_mutex_lock(&mtx);
    }
    void Unlock()
    {
        pthread_mutex_unlock(&mtx);
    }
    void Wait()
    {
        pthread_cond_wait(&cond,&mtx);
    }
    void Wake()
    {
        pthread_cond_signal(&cond);
    }
    bool IsEmpty()
    {
        return q.empty();
    }
    void Put(Task* t)
    {
        Lock();
        q.push(t);
        Unlock();
        Wake();
    }
    void Get(Task*& t)
    {
        t=q.front();
        q.pop();
    }
public:
    static ThreadPool* getInstance(int num=NUM)
    {
        static pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
        if(tp==nullptr)
        {
            pthread_mutex_lock(&lock);
            if(tp==nullptr)
            {
                tp=new ThreadPool(num);
                if(!tp->InitThreadPool())
                exit(-1);
            }
            pthread_mutex_unlock(&lock);
        }
        return tp;
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&mtx);
        pthread_cond_destroy(&cond);
    }
    //每个线程执行的例程
    static void* Runtine(void* arg)
    {
        pthread_detach(pthread_self());//线程分离
        ThreadPool* tp=(ThreadPool*)arg;
        while(true)
        {
            tp->Lock();
            while(tp->IsEmpty())
                tp->Wait();
            Task* t;
            tp->Get(t);
            LOG(INFO,"GET Task");
            tp->Unlock();
            t->ProcessOn();
            LOG(INFO,"Process On Task OK");
            delete t;
        }
    }
    bool InitThreadPool()
    {
        pthread_mutex_init(&mtx,nullptr);
        pthread_cond_init(&cond,nullptr);
        pthread_t tid[num];
        for(int i=0;i<num;i++)
        {
            if(pthread_create(tid+i,nullptr,Runtine,this)!=0)
            {
                LOG(FATAL,"ThreadPool Init Fail...");
                return false;
            }
        }
        LOG(INFO,"ThreadPool Init Success");
        return true;
    }
};
ThreadPool* ThreadPool::tp=nullptr;
ThreadPool::CGarbo ThreadPool::cg;